﻿using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Linq;
using CompactMapper.Orm.Annotations;

namespace CompactMapper.Orm.Tests.Transactions
{
    /// <summary>
    /// Summary description for Transactions
    /// </summary>
    [TestClass]
    public class Transactions : OrmInMemoryTest
    {
        private static TransactionsParent CreateTransactionsParent()
        {
            var transactionsParent = new TransactionsParent()
                             {
                                 Name = "TransactionsParent" + DateTime.Now.Ticks
                             };
            var numChildren = new Random(DateTime.Now.Millisecond).Next(1, 10);
            for (int i = 0; i < numChildren; i++)
                transactionsParent.AddTransactionsChild(CreateTransactionsChild());
            return transactionsParent;
        }

        private static TransactionsChild CreateTransactionsChild()
        {
            return new TransactionsChild() { Name = "TransactionsChild" + DateTime.Now.Ticks };
        }

        [TestMethod]
        public void InsertABigCollectionInASingleTransaction()
        {
            var transactionsParents = new List<TransactionsParent>();
            var numParents = new Random(DateTime.Now.Millisecond).Next(1, 1000);
            for (int i = 0; i < numParents; i++)
            {
                transactionsParents.Add(CreateTransactionsParent());
            }
            using (var unitOfWork = GetKeyedUnitOfWork<TransactionsParent>())
            {
                Assert.AreEqual(0, unitOfWork.GetAll().Count());
                unitOfWork.MakePersistent(transactionsParents);
            }
            using (var unitOfWork = GetKeyedUnitOfWork<TransactionsParent>())
            {
                var read = unitOfWork.GetAll();
                Assert.IsTrue(transactionsParents.Count() > 0);
                Assert.AreEqual(transactionsParents.Count(), read.Count());
                Assert.IsTrue(transactionsParents.SelectMany(p => p.TransactionsChildren).Count() > 0);
                Assert.AreEqual(transactionsParents.SelectMany(p => p.TransactionsChildren).Count(), read.SelectMany(p => p.TransactionsChildren).Count());
            }
        }

        [TestMethod]
        public void TryToDeleteAndInsert_ThrowAndExceptionDuringInsertion_ExisingEntitiesAreUntouched()
        {
            var parent = CreateTransactionsParent();
            using (var unitOfWork = GetKeyedUnitOfWork<TransactionsParent>())
            {
                Assert.AreEqual(0, unitOfWork.GetAll().Count());
                unitOfWork.MakePersistent(parent);
            }
            using (var unitOfWork = GetKeyedUnitOfWork<TransactionsParent>())
            {
                Assert.AreEqual(parent, unitOfWork.GetAll().Single());
            }

            var cloned = new TransactionsParent() { Name = "cloned", Key = parent.Key };
            using (var unitOfWork = GetKeyedUnitOfWork<TransactionsParent>(new ThrowOnInsertMappings(UnitOfWork.UnitOfWorkFactory.Mappings)))
            {
                unitOfWork.Delete(parent);
                unitOfWork.MakePersistent(cloned);
            }

            using (var unitOfWork = GetKeyedUnitOfWork<TransactionsParent>())
            {
                Assert.AreEqual(parent.Name, unitOfWork.GetAll().Single().Name);
            }
        }
    }
}
